using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Net;
using System.IO;

namespace SharepointListMigrator
{
	public class ListCloner
	{
		
		private NetworkCredential credentials = null;

		public ListCloner(string username, string password, string domain)
		{
			credentials = WebServiceHelper.CreateCredentialToken(username, password, domain); //this validates the parameters too
		}

		public void CloneList(string sourceListUrl, string destinationSiteUrl)
		{
			if (string.IsNullOrEmpty(sourceListUrl))
				throw new ArgumentNullException("The parameter 'sourceListUrl' cannot be null or blank.");
			if (string.IsNullOrEmpty(destinationSiteUrl))
				throw new ArgumentNullException("The parameter 'destinationSiteUrl' cannot be null or blank.");

			//spit the source list url
			string[] split = sourceListUrl.Split('/');//tokenize
			string listName = split[split.Length-1];//get the last word

			XmlNode sourceListDetail = GetSourceListDetails(sourceListUrl, listName);

#if DEBUG
			//log results
			using (StreamWriter writer = new StreamWriter(string.Format("{0}-CloneList-SourceListDetails.xml", listName)))
				writer.Write(sourceListDetail.OuterXml);
#endif

			XmlNode newListDetail = CreateDestinationList(destinationSiteUrl, sourceListDetail.Attributes["Title"].Value, int.Parse(sourceListDetail.Attributes["ServerTemplate"].Value));
			XmlNode results = CreateFields(destinationSiteUrl, sourceListDetail, newListDetail);

			//TODO - do something with the results.
		}


		private XmlNode GetSourceListDetails(string sourceListUrl,string listName)
		{
			if (string.IsNullOrEmpty(sourceListUrl))
				throw new ArgumentNullException("The parameter 'sourceListUrl' cannot be null or blank.");
			if (string.IsNullOrEmpty(listName))
				throw new ArgumentNullException("The parameter 'listName' cannot be null or blank.");

			string[] split = sourceListUrl.Split('/');//tokenize
			//TODO - this isnt correct and will need tuning
			string sourceSiteUrl = split[0] + "/" + split[1] + "/" + split[2] ;//get the last word

			XmlNode listDetail = null;
			using (Source.Lists.Lists sourceService = WebServiceHelper.GetSourceWebService(sourceSiteUrl, credentials))
			{
				listDetail = sourceService.GetList(listName);
			}
			return listDetail;
		}

		private XmlNode CreateDestinationList(string destinationSiteUrl, string listName, int listType )
		{
			if (string.IsNullOrEmpty(destinationSiteUrl))
				throw new ArgumentNullException("The parameter 'sourceListUrl' cannot be null or blank.");
			if (string.IsNullOrEmpty(listName))
				throw new ArgumentNullException("The parameter 'listName' cannot be null or blank.");

			XmlNode listDetail = null;
			using (Destination.Lists.Lists destinationService = WebServiceHelper.GetDestinationWebService(destinationSiteUrl, credentials))
			{
				listDetail = destinationService.AddList(listName, string.Empty, listType);
			}
			return listDetail;
		}

		private XmlNode CreateFields(string destinationSiteUrl, XmlNode sourceListDetails, XmlNode newListDetails)
		{
			if (string.IsNullOrEmpty(destinationSiteUrl))
				throw new ArgumentNullException("The parameter 'sourceListUrl' cannot be null or blank.");
			if (sourceListDetails == null)
				throw new ArgumentNullException("The parameter 'sourceListDetails' cannot be null");
			if (newListDetails == null)
				throw new ArgumentNullException("The parameter 'newListDetails' cannot be null");

			//Create the xml
			StringBuilder xmlInstructions = new StringBuilder();

			XmlNode sourceFields = sourceListDetails.ChildNodes[0];
			XmlNode newFields = newListDetails.ChildNodes[0];
			string listName = newListDetails.Attributes["Title"].Value;
			string version = newListDetails.Attributes["Version"].Value;

			int counter =1;
			foreach(XmlNode sourceField in sourceFields.ChildNodes)
			{
				if (!string.IsNullOrEmpty(sourceField.Attributes["Name"].Value)) //we want real fields
				{
					//does the file not already exist?
					if (newFields.OuterXml.IndexOf(String.Format("Name='{0}'", sourceField.Attributes["Name"].Value)) >= 0)
					{
						xmlInstructions.Append(string.Format("<Method ID='{0}'>{1}</Method>",counter, sourceField.InnerXml));

						//xmlInstructions.Append(string.Format("<Method ID='{0}'><Field ReadOnly='{1}' Type='{2}' PrimaryKey='{3}' DisplayName='{4}' FromBaseType='{5}' /></Method>",
						//                          counter,
						//                          sourceField.Attributes["ReadOnly"] == null ? string.Empty : sourceField.Attributes["ReadOnly"].Value,
						//                          sourceField.Attributes["Type"] == null ? string.Empty : sourceField.Attributes["Type"].Value,
						//                          sourceField.Attributes["PrimaryKey"] == null ? string.Empty : sourceField.Attributes["PrimaryKey"].Value,
						//                          sourceField.Attributes["DisplayName"] == null ? string.Empty : sourceField.Attributes["DisplayName"].Value,
						//                          sourceField.Attributes["FromBaseType"] == null ? string.Empty : sourceField.Attributes["FromBaseType"].Value));
						counter++;
					}
				}
			}
			XmlDocument doc = new XmlDocument();
			XmlNode ndNewFields = doc.CreateNode(XmlNodeType.Element, "Fields", "");
			ndNewFields.InnerXml = xmlInstructions.ToString();

#if DEBUG
			//log results
			using (StreamWriter writer = new StreamWriter(string.Format("{0}-CloneList-NewFields.xml", listName)))
				writer.Write(ndNewFields.OuterXml);
#endif


			XmlNode results = null;
			using (Destination.Lists.Lists destinationService = WebServiceHelper.GetDestinationWebService(destinationSiteUrl, credentials))
			{
				results = destinationService.UpdateList(listName, null, ndNewFields, null, null, version);
			}

			return results;
		}


		
	}
}
